package edu.asu.acns.android;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.Certificate;
import java.text.DecimalFormat;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.Debug;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class DEMLauncher extends Activity {
	//TODO -change ip
	public static final String CLOUD_IP = "http://184.73.36.139";
	public static final String LOGIN_URL = CLOUD_IP+"/main/login.aspx?";
	public static final String CES_URL = "";
	public static final String VIEW_PATIENT_INFO_URL = CLOUD_IP+"/pws/PatientViewWS.asmx/GetPatientInfo?";
	public static final String COMPUTE_PATIENT_STATS_URL = CLOUD_IP+"/cws/CalculateStatsWS.asmx/GetPatientStats?pid=";

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.loginscreen);
		Button b = (Button) findViewById(R.id.SignInButton);
		b.setOnClickListener(new LoginButtonClickListener(this));
		Intent demIntent = new Intent(this, DeviceElasticityManager.class);
		this.startService(demIntent);
		Editor e = this.getApplication().getSharedPreferences("cesfile", 1)
		.edit();
		e.putString("outputurl0","");
		e.putString("battery", "");
		e.commit();
		
		//Intent intent = new Intent(Intent.ACTION_BATTERY_LOW);
		//this.sendBroadcast(intent);
		
	}

	public static void displayPatientInfo(Activity activity, String pid) {

		// String pid = "1";
		// remove the hardcode
		if (pid != null && !"".equals(pid)) {

			String patientviewURL = VIEW_PATIENT_INFO_URL + "pid=" + pid;
			// connect to the getPatientRecord service and get the data
			String valueString = getDataFromCloud(patientviewURL);
			//TODO - remove hardcode
			  /*String valueString = "<PatientInfo>" + "<PName>anshuman</PName>"
			  + "<Age>23</Age>" + "<Sex>M</Sex>" + "<DName>no disease</DName>"
			  + "<Bp>100</Bp>" + "<HCount>100</HCount>" + "<HRate>100</HRate>"
			  + "</PatientInfo>";*/
			 
			// parse this string
			PatientViewParser parser = new PatientViewParser(valueString);
			parser.parse();

			// prepare the view
			activity.setContentView(R.layout.patientinfo);

			// populate the values
			TextView nameView = (TextView) activity
					.findViewById(R.id.NameTextBox);
			nameView.setText(parser.getPname());
			// nameView.setText("anshuman");
			TextView ageView = (TextView) activity.findViewById(R.id.AgeBox);
			ageView.setText(parser.getAge());
			// ageView.setText("23");
			TextView genderView = (TextView) activity
					.findViewById(R.id.GenderBox);
			genderView.setText(parser.getSex());
			TextView diseaseView = (TextView) activity
					.findViewById(R.id.DiseaseBox);
			diseaseView.setText(parser.getDisease());
			TextView bpView = (TextView) activity.findViewById(R.id.BPBox);
			bpView.setText(parser.getBp());
			TextView hcountView = (TextView) activity.findViewById(R.id.HLBox);
			hcountView.setText(parser.getHcount());
			TextView hrView = (TextView) activity.findViewById(R.id.HRBox);
			hrView.setText(parser.getHrate());
			Button b = (Button) activity.findViewById(R.id.StatViewButton);
			b.setOnClickListener(new ViewStatsButtonClickListener(activity));

			Button lgout = (Button) activity.findViewById(R.id.LogoutButton);
			lgout.setOnClickListener(new LogoutButtonClickListener(activity));

			Editor e = activity.getApplication().getSharedPreferences("cesfile", 1)
			.edit();
			e.putString("bp", parser.getBp());
			e.putString("hr", parser.getHrate());
			e.putString("hc", parser.getHcount());
			e.commit();
			
			
		} else {
			// display the same login page, with error message
			activity.setContentView(R.layout.loginscreen);
			Button b = (Button) activity.findViewById(R.id.SignInButton);
			b.setOnClickListener(new LoginButtonClickListener(activity));
			/*
			 * setContentView(R.layout.login); tv1 =
			 * (EditText)findViewById(R.id.text1); tv1.setText("Invalid user");
			 */
		}

	}

	@Override
	public void finish() {
	}

	@Override
	public void finishActivity(int requestCode) {
		super.finishActivity(requestCode);
	}

	public void onClick_original(View v) {
		TextView txt = (TextView) v;
		/*
		 * StringBuilder debugStr = new StringBuilder("");
		 * debugStr.append(" Debug.getLoadedClassCount()="
		 * ).append(Debug.getLoadedClassCount());
		 * debugStr.append(" Debug.getNativeHeapFreeSize()="
		 * ).append(Debug.getNativeHeapFreeSize());
		 */
		String outputurl = this.getApplication().getSharedPreferences(
				"cesfile", 1).getString("outputurl0", "");
		txt.setClickable(true);
		txt.setText(outputurl);
		setContentView(txt);

	}

	/*
	 * public void onClick(View v) { //setContentView(txt); //if user clicked on
	 * login button Button b = (Button)v; if(true){ handleLogin(); }else{ //user
	 * clicked on view stats button handleViewStats(); }
	 * 
	 * }
	 */

	
	 public static String decrypt(String text, String key) {
         try{
         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
         byte[] keyBytes= new byte[16];
         byte[] b= key.getBytes("UTF-8");
         int len= b.length;
         if (len > keyBytes.length) len = keyBytes.length;
         System.arraycopy(b, 0, keyBytes, 0, len);
         SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
         IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
         cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);

        // BASE64Decoder decoder = new BASE64Decoder();
        // byte [] results = cipher.doFinal(decoder.decodeBuffer(text));
         //return new String(results,"UTF-8");
         return null;
         }
         catch(Exception e)
         {
             System.out.println("Exception occured in Decrypt");
             return null;
         }
         }

	
	public static String getDataFromCloud(String URL) {
		int BUFFER_SIZE = 2000;
		InputStream in = null;
		try {
			in = openHttpConnection(URL);
		} catch (IOException e1) {
			e1.printStackTrace();
			return "";
		}

		InputStreamReader isr = new InputStreamReader(in);
		int charRead;
		String str = "";
		char[] inputBuffer = new char[BUFFER_SIZE];
		try {
			while ((charRead = isr.read(inputBuffer)) > 0) {
				// ---convert the chars to a String---
				String readString = String
						.copyValueOf(inputBuffer, 0, charRead);
				str += readString;
				inputBuffer = new char[BUFFER_SIZE];
			}
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		}
		return str;
	}

	public static String getDataFromCloud_https(String url)
	  {
	    StringBuilder sb = new StringBuilder();
		try{
		//String httpsURL = "https://your.https.url.here/";
	    URL myurl = new URL(url);
	    HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
	    //Certificate []cert  = con.getServerCertificates();
	    //cert[0].
	    InputStream ins = con.getInputStream();
	    InputStreamReader isr=new InputStreamReader(ins);
	    BufferedReader in =new BufferedReader(isr);

	    String input= null;

	    while ((input = in.readLine()) != null){
	    	sb.append(input);
	    }
	        

	    in.close();
	    }catch(Exception e){
	    e.printStackTrace();	
	    }
	    return sb.toString();
	  }
	
	private static InputStream openHttpConnection(String urlString)
			throws IOException {
		InputStream in = null;
		int response = -1;

		URL url = new URL(urlString);
		URLConnection conn = url.openConnection();

		if (!(conn instanceof HttpURLConnection))
			throw new IOException("Not an HTTP connection");

		try {
			HttpURLConnection httpConn = (HttpURLConnection) conn;
			//httpConn.
			httpConn.setAllowUserInteraction(false);
			httpConn.setInstanceFollowRedirects(true);
			httpConn.setRequestMethod("GET");
			httpConn.connect();

			response = httpConn.getResponseCode();
			if (response == HttpURLConnection.HTTP_OK) {
				in = httpConn.getInputStream();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new IOException("Error connecting");
		}
		return in;
	}

}

class LogoutButtonClickListener implements OnClickListener {

	private Activity activity;

	public LogoutButtonClickListener(Activity act) {
		activity = act;
	}

	@Override
	public void onClick(View v) {
		activity.setContentView(R.layout.loginscreen);
		Button b = (Button) activity.findViewById(R.id.SignInButton);
		b.setOnClickListener(new LoginButtonClickListener(activity));

	}

}

class ViewPatientInfoButtonClickListener implements OnClickListener {

	private Activity activity;

	public ViewPatientInfoButtonClickListener(Activity act) {
		activity = act;
	}

	public void onClick(View arg0) {

		String pid = activity.getApplication().getSharedPreferences("cesfile",
				1).getString("pid", "");

		DEMLauncher.displayPatientInfo(activity, pid);
	}

}

class ViewStatsButtonClickListener implements OnClickListener {

	private Activity activity;

	public ViewStatsButtonClickListener(Activity act) {
		activity = act;
	}

	@Override
	public void onClick(View v) {

		String sBp = activity.getApplication().getSharedPreferences("cesfile", 1).getString("bp","");
		String sHr = activity.getApplication().getSharedPreferences("cesfile", 1).getString("hr","");
		String sHc = activity.getApplication().getSharedPreferences("cesfile", 1).getString("hc","");
			
		int bp = -1;
		int hl = -1;
		int hr = -1;

		try {
			bp = new Integer(sBp).intValue();
			hl = new Integer(sHr).intValue();
			hr = new Integer(sHc).intValue();
		} catch (Exception e) {
			bp = -1;
			hl = -1;
			hr = -1;
		}
		// prepare the view
		activity.setContentView(R.layout.patientstats);

		// write the client request to the shared memory
		Editor e = activity.getApplication().getSharedPreferences("cesfile", 1)
				.edit();
		e.putString("clientrequest0", "calculatestats");
		e.commit();

		// check the shared memory for DEM response
		String outputurl = activity.getApplication().getSharedPreferences(
				"cesfile", 1).getString("outputurl0", "");
		//TODO remove hardcode
		//outputurl = "local";
		
		String pid = activity.getApplication().getSharedPreferences(
				"cesfile", 1).getString("pid", "");

		// generate the view
		activity.setContentView(R.layout.patientstats);
		
		StatsManager stats = new StatsManager();
		// compute stats locally
		if ("".equals(outputurl) || "local".equals(outputurl)
				|| outputurl == null) {
			stats.computeOnDevice(bp, hl, hr);
			((TextView) activity.findViewById(R.id.StatusText)).setText("Computed on the device");
			
		}
		// compute on the cloud
		else {
			stats.computeOnCloud(outputurl+"?pid="+pid);
			((TextView) activity.findViewById(R.id.StatusText)).setText("Computed on the cloud(location = "+outputurl+")");
		}


		TextView bpView = (TextView) activity.findViewById(R.id.BPStatsBox);
		bpView.setText(stats.getBpStats());

		TextView hlView = (TextView) activity.findViewById(R.id.HLStatsBox);
		hlView.setText(stats.getHcountStats());

		TextView hrView = (TextView) activity.findViewById(R.id.HRStatsBox);
		hrView.setText(stats.getHrateStats());

		Button b = (Button) activity.findViewById(R.id.PatientViewButton);
		b.setOnClickListener(new ViewPatientInfoButtonClickListener(activity));

	}

}

class StatsManager {

	private String bpStats;
	private String hcountStats;
	private String hrateStats;

	public void computeOnDevice(int bpvalue, int hcountvalue, int hratevalue) {

		String pbpstats = "No info";

		if (bpvalue < 120) {
			pbpstats = "Normal";
		}
		if (bpvalue >= 120 && bpvalue <= 139) {
			pbpstats = "Prehypertension";
		}
		if (bpvalue >= 140 && bpvalue <= 159) {
			pbpstats = "High BP Stage 1";
		}
		if (bpvalue >= 160 && bpvalue < 180) {
			pbpstats = "High BP Stage 2";
		}
		if (bpvalue >= 180) {
			pbpstats = "Hypertensive Crisis";
		}
		String phcountstats = "No info";

		if (hcountvalue <= 18 && hcountvalue >= 11) {
			phcountstats = "Normal";
		} else {
			phcountstats = "Dangerous Level";
		}

		String phratestats = "No info";
		if (hratevalue <= 100 && hratevalue >= 50) {
			phratestats = "Normal";
		} else {
			phratestats = "Dangerous Level";
		}
		bpStats = pbpstats;
		hcountStats = phcountstats;
		hrateStats = phratestats;

	}

	public String getBpStats() {
		return bpStats;
	}

	public String getHcountStats() {
		return hcountStats;
	}

	public String getHrateStats() {
		return hrateStats;
	}

	public void computeOnCloud(String url) {
		String xml = DEMLauncher.getDataFromCloud(url);

		
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			InputStream fis = new ByteArrayInputStream(xml.getBytes());
			Document doc = db.parse(fis);

			Element topElement = doc.getDocumentElement();

			NodeList nodeList = topElement.getChildNodes();
			for (int elementIndex = 0; elementIndex < nodeList.getLength(); elementIndex++) {
				Node element = nodeList.item(elementIndex);
				if (element instanceof Element) {

					// System.out.println("["+trkpts.item(elementIndex)+"]");
					if (element.getNodeName().equals("BPStats")) {
						// this.pname = trkpt.getFirstChild().getNodeType();
						this.bpStats = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("HCountStats")) {
						this.hcountStats = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("HRateStats")) {
						this.hrateStats = element.getFirstChild().getNodeValue();
					}
				}// end instance of
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		
		
	}

}

class LoginButtonClickListener implements OnClickListener {

	private Activity activity;

	public LoginButtonClickListener(Activity act) {
		activity = act;
	}

	@Override
	public void onClick(View v) {

		EditText tv1 = (EditText) activity.findViewById(R.id.LogInIDEditBox);
		EditText tv2 = (EditText) activity.findViewById(R.id.passwordEditBox);
		String userName = tv1.getEditableText().toString();
		String pwd = tv2.getEditableText().toString();
		// encrypt pwd and send to login service on cloud
		String loginURL = DEMLauncher.LOGIN_URL + "pname=" + userName + "&pwd="
				+ RSAEncrypter.keyEnc(pwd,83,25807);
		// connect to cloud, login-service to check if authentication succeeds
		//TODO
		String pid = DEMLauncher.getDataFromCloud(loginURL);
		//uncomment
		//String pid = "1";
		try{
			pid = pid.substring(0, 1);
			new Integer(pid);
		}catch(Exception e){
			pid = "";
		}
		// display patient info
		Editor e = activity.getApplication().getSharedPreferences("cesfile", 1)
				.edit();
		e.putString("pid", pid);
		e.commit();
		DEMLauncher.displayPatientInfo(activity, pid);

	}

}

class PatientViewParser {

	private String xml;

	private String pname;
	private String age;
	private String sex;
	private String disease;
	private String bp;
	private String hcount;
	private String hrate;

	public String getPname() {
		return pname;
	}

	public String getAge() {
		return age;
	}

	public String getSex() {
		return sex;
	}

	public String getDisease() {
		return disease;
	}

	public String getBp() {
		return bp;
	}

	public String getHcount() {
		return hcount;
	}

	public String getHrate() {
		return hrate;
	}

	public PatientViewParser(String xml) {

		this.xml = xml;
		this.age = "23";
		this.bp = "100";
		this.disease = "no disease";
		this.hcount = "100";
		this.hrate = "100";
		this.pname = "anshuman";
		this.sex = "M";

	}

	public void parse() {

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			InputStream fis = new ByteArrayInputStream(xml.getBytes());
			Document doc = db.parse(fis);

			Element topElement = doc.getDocumentElement();

			NodeList nodeList = topElement.getChildNodes();
			for (int elementIndex = 0; elementIndex < nodeList.getLength(); elementIndex++) {
				Node element = nodeList.item(elementIndex);
				if (element instanceof Element) {

					// System.out.println("["+trkpts.item(elementIndex)+"]");
					if (element.getNodeName().equals("PName")) {
						// this.pname = trkpt.getFirstChild().getNodeType();
						this.pname = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("Age")) {
						this.age = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("Sex")) {
						this.sex = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("DName")) {
						this.disease = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("Bp")) {
						this.bp = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("HCount")) {
						this.hcount = element.getFirstChild().getNodeValue();
					} else if (element.getNodeName().equals("HRate")) {
						this.hrate = element.getFirstChild().getNodeValue();
					}
				}// end instance of
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}


class RSAEncrypter {

	/**
	 * @param args
	 *            the command line arguments
	 */

	public static String keyEnc(String str, int e, int n) {
		int i, X, j;
		long Y;

		DecimalFormat format = new DecimalFormat("00000000");
		String EncryptedString = new String();
		int strLength = str.length();

		char c = 0;

		for (i = 0; i < strLength; i++) {
			c = str.charAt(i);
			System.out.print(c);
			System.out.printf("%d\n", (int) c);
			Y = crypt((int) c, e, n);

			EncryptedString += format.format(Y);

		}
		return EncryptedString;

	}

	long isPrime(long n) {
		long b = 1;
		for (long i = 2; i < n; i++)
			if (n % i == 0) {
				b = 0;
				break;
			}
		return b;
	}

	long Power(long x, long y) {
		long ans = 1;
		if (x == 1)
			return x;
		for (long i = 1; i <= y; i++)
			ans *= x;
		return (ans);
	}

	public static String ToBin(int x) {
		char[] ans = new char[20];
		int i = 0;
		while (x >= 1) {
			if (x % 2 == 1)
				ans[i] = '1';
			else
				ans[i] = '0';
			x /= 2;
			i++;
		}
		if (x == 1)
			ans[i] = '1';
		i++;
		// ans[i]='\0';

		StringBuffer dest = new StringBuffer(i);
		for (int j = i - 1; j >= 0; j--) {
			dest.append(ans[j]);
		}

		/*
		 * String temp = ans.toString(); String ans1 = new
		 * StringBuffer(temp).reverse().toString();
		 */

		System.out.println(dest.toString());
		return dest.toString();
	}

	public static long crypt(int x, int key, int n) // (x^y)%z //Method 2
	{
		String B;
		B = ToBin(key);
		long ans = 1;
		int c = 1;
		for (int i = 0; i < B.length(); i++) {
			c = 2 * c;
			ans = (ans * ans) % n;
			if (B.charAt(i) == '1') {
				c = c + 1;
				ans = (ans * x) % n;
			}
		}
		return (ans);
	}

	int Bin2Num(String s) {
		int ans = 0;
		int i, j;
		for (j = 0, i = 7; i >= 0; j++, i--) {
			if (s.charAt(i) == '1')
				ans += Power(2, j);
		}
		return ans;
	}

	public static void main(String[] args) {
		int p = 131;
		int q = 197;
		int n = 0;
		n = (p * q);
		int n1 = (p - 1) * (q - 1);
		int e = 83;
		int d = 307;

		String Enc = keyEnc("pwd=anshuman123", e, n);

		System.out.println(Enc);
		System.out.println(Enc.length());
	}
}


